﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace IntoNails.Models
{
    [Serializable]
    public class Service : AbstractModel<Guid>, ISerializable
    {
        #region Constructors

        protected Service()
        {
        }

        public Service(SerializationInfo info, StreamingContext context)
        {
            this.UniqueCode = (Guid) info.GetValue("UniqueCode", typeof (Guid));
            this.DisplayName = info.GetString("DisplayName");
            this.Minutes = info.GetInt32("Minutes");
            this.Price = info.GetDouble("Price");
            this.AssociatedCategory = (Category) info.GetValue("AssociatedCategory", typeof (Category));
            this.PriceExceptions = (List<ServicePriceException>) info.GetValue("PriceExceptions", typeof (List<ServicePriceException>));
            this.CreatedDate = info.GetDateTime("CreatedDate");
            this.UpdatedDate = info.GetDateTime("UpdatedDate");
            this.IsValid = info.GetBoolean("IsValid");
        }

        #endregion

        #region Properties

        public int Minutes { get; set; }
        public double Price { get; set; }

        public List<ServicePriceException> PriceExceptions { get; set; }

        public Category AssociatedCategory { get; set; }

        #endregion

        public static Service CreateNewService()
        {
            return new Service()
                       {
                           UniqueCode = Guid.NewGuid(),
                           AssociatedCategory = null,
                           PriceExceptions = new List<ServicePriceException>()
                       };
        }

        public static Service CreateService(string serviceName, int minutes, double price, Category associatedCategory, List<ServicePriceException> priceExceptions)
        {
            return new Service
                       {
                           UniqueCode = Guid.NewGuid(),
                           DisplayName = serviceName,
                           Minutes = minutes,
                           Price = price,
                           AssociatedCategory = associatedCategory,
                           PriceExceptions = priceExceptions,
                           CreatedDate = DateTime.Now,
                           UpdatedDate = DateTime.Now,
                           IsValid = true
                       };
        }

        #region Implementation of ISerializable

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("UniqueCode", this.UniqueCode);
            info.AddValue("DisplayName", this.DisplayName);
            info.AddValue("Minutes", this.Minutes);
            info.AddValue("Price", this.Price);
            info.AddValue("AssociatedCategory", this.AssociatedCategory);
            info.AddValue("PriceExceptions", this.PriceExceptions);
            info.AddValue("CreatedDate", this.CreatedDate);
            info.AddValue("UpdatedDate", this.UpdatedDate);
            info.AddValue("IsValid", this.IsValid);
        }

        #endregion

        #region Object Overriden

        public override string ToString()
        {
            return string.Format("ID: {0} | Name: {1}", this.UniqueCode, this.DisplayName);
        }

        public override int GetHashCode()
        {
            int hashCode = 0;

            unchecked
            {
                hashCode += this.UniqueCode.GetHashCode();
                hashCode += this.DisplayName.GetHashCode();
                hashCode += this.Minutes.GetHashCode();
                hashCode += this.Price.GetHashCode();
                hashCode += this.AssociatedCategory == null ? 0 : this.AssociatedCategory.GetHashCode();
                hashCode += this.PriceExceptions.GetHashCode();
                hashCode += this.CreatedDate.GetHashCode();
                hashCode += this.UpdatedDate.GetHashCode();
                hashCode += this.IsValid.GetHashCode();
            }

            return hashCode;
        }

        public override bool Equals(object obj)
        {
            Service other = obj as Service;
            if (other == null)
                return false;

            return this.UniqueCode == other.UniqueCode;
        }

        #endregion
    }
}
